package impl

import (
	"context"
	"fmt"
	"go-caipu/pkg/plugins/log"
	"go-caipu/pkg/services/dto"
	"go-caipu/pkg/services/monitor/onlineuser"
	"go-caipu/pkg/services/monitor/onlineuser/models"
	"gorm.io/gorm"
	"time"
)

type sqlStore struct {
	db     *gorm.DB
	logger log.Logger
}

func ProvideStore(db *gorm.DB) sqlStore {
	return sqlStore{
		db:     db,
		logger: log.New("online.store"),
	}
}

func (s sqlStore) GetOnlineUserPage(ctx context.Context, cmd onlineuser.GetOnlinePageCommand) (data []onlineuser.OnlineCommand, num int64, err error) {
	var items []models.SysOnlineUser
	err = s.db.Model(&models.SysOnlineUser{}).Scopes(
		dto.MakeCondition(cmd.GetNeedSearch()),
		dto.Paginate(cmd.GetPageSize(), cmd.GetPageIndex()),
	).Find(&items).Limit(-1).Offset(-1).Count(&num).Error
	if err != nil {
		return
	}
	for _, v := range items {
		data = append(data, OnlineUserToDTO(v))
	}
	return
}
func OnlineUserToDTO(cmd models.SysOnlineUser) (model onlineuser.OnlineCommand) {
	model.Id = cmd.Id
	model.UserId = cmd.UserId
	model.Token = cmd.Token
	model.UserName = cmd.UserName
	model.NickName = cmd.NickName
	model.Ip = cmd.Ip
	model.Location = cmd.Location
	model.Browser = cmd.Browser
	model.Os = cmd.Os
	model.LoginTime = cmd.LoginTime.Format("2006-01-02 15:04:05")
	model.LastActiveAt = cmd.LastActiveAt.Format("2006-01-02 15:04:05")
	return
}

func (s sqlStore) Get(ctx context.Context, token string) (result *onlineuser.OnlineCommand, err error) {
	tx := s.db.Model(&models.SysOnlineUser{}).Where("token= ?", token)
	err = tx.First(&result).Error
	return result, err
}
func ConvertToDT(model onlineuser.OnlineCommand, cmd *models.SysOnlineUser) {
	cmd.Id = model.Id
	cmd.UserId = model.UserId
	cmd.Token = model.Token
	cmd.UserName = model.UserName
	cmd.NickName = model.NickName
	cmd.Ip = model.Ip
	cmd.Location = model.Location
	cmd.Browser = model.Browser
	cmd.Os = model.Os

}

func (s sqlStore) Set(ctx context.Context, cmd onlineuser.OnlineCommand, timeout int64) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var data models.SysOnlineUser
	ConvertToDT(cmd, &data)
	data.LoginTime = time.Now()
	data.LastActiveAt = time.Now()
	err = tx.Create(&data).Error
	if err != nil {
		s.logger.Error(fmt.Sprintf("insert OnlineUser error:%s", err.Error()))
		return err
	}
	return nil
}

func (s sqlStore) Remove(ctx context.Context, token string) error {
	//
	err := s.db.Where("token= ?", token).Delete(&models.SysOnlineUser{}).Error
	if err != nil {
		return err
	}
	return nil
}

// IsSessionValid 检查会话是否有效
func (s sqlStore) IsSessionValid(ctx context.Context, token string) (bool, error) {
	var count int64
	err := s.db.Model(&models.SysOnlineUser{}).Where("token= ?", token).Count(&count).Error
	if err != nil {
		return false, err
	}
	//更新最后活跃时间
	if count == 0 {
		return false, nil
	}

	err = s.db.Model(&models.SysOnlineUser{}).Where("token= ?", token).Update("last_active_at", time.Now()).Error
	if err != nil {
		return false, err
	}
	return true, nil
}

func (s sqlStore) DeleteExpiredLogin(ctx context.Context, timeout int64) (err error) {

	if timeout <= 0 {
		return nil
	}
	// 计算超时时间点：当前时间减去指定的秒数
	expiredTime := time.Now().Add(-time.Duration(timeout) * time.Second)

	// 删除登录时间早于expiredTime的记录
	result := s.db.Model(&models.SysOnlineUser{}).Where("login_time < ?", expiredTime).Delete(&models.SysOnlineUser{})

	if result.Error != nil {
		return result.Error
	}

	return nil
}
